package com.cdp.web.controller.system.openFeign;

import com.cdp.common.core.domain.AjaxResult;
import com.cdp.system.dto.PythonBelowNamicDTO;
import com.cdp.system.dto.PythonUpperBelowDTO;
import com.cdp.system.dto.PythonUpperNamicDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 三个三角算法
 */
@RestController
@RequestMapping
@Slf4j
public class FeignControllerTwo {


    @Autowired
    private FileClient fileClient;


    /**
     * 下三角Second
     */
    @PostMapping("/feign/belowNamic/second")
    public AjaxResult unusualDetectionSecond(@RequestBody PythonBelowNamicDTO pythonBelowNamicDTO) {
        String xlsxFile = pythonBelowNamicDTO.getXlsxFile();

        List<String> selectFeature = pythonBelowNamicDTO.getSelectFeature();

        // 处理 selectFeature 替换
        replaceStoneAndSandFeatures(selectFeature);
        // 递归检查 pythonBelowNamicDTO 中是否包含 NaN
        if (containsNaN(pythonBelowNamicDTO)) {
            return AjaxResult.error("数据错误，包含 NaN");
        }

        // 调用接口
        AjaxResult ajaxResult = null;
        try {

            try {
                filterSelectFeatureByExcelData(xlsxFile, selectFeature);
            } catch (Exception e) {
                log.error("读取Excel或处理列异常", e);
                return AjaxResult.error("Excel文件处理失败");
            }


            ajaxResult = fileClient.belowNamic(pythonBelowNamicDTO);
            // 处理返回结果，去除 NaN
            cleanNaNValues(ajaxResult);

            return ajaxResult;
        } catch (Exception e) {
            log.error("/belowNamic/second算法报错:{}", e.getMessage());
            return AjaxResult.error("算法未预测出结果,请重选新数据重试！", e);
        }


    }


    /**
     * 上三角Second
     */

    @PostMapping("/feign/upper/namic/second")
    public AjaxResult upperNamicSecond(@RequestBody PythonUpperNamicDTO pythonBelowNamicDTO) {
        List<String> selectFeature = pythonBelowNamicDTO.getSelectFeature();
        String xlsxFile = pythonBelowNamicDTO.getXlsxFile();
        // 处理 selectFeature 替换
        replaceStoneAndSandFeatures(selectFeature);
        // 递归检查 pythonBelowNamicDTO 中是否包含 NaN
        if (containsNaN(pythonBelowNamicDTO)) {
            return AjaxResult.error("数据错误，包含 NaN");
        }

        // 调用接口
        AjaxResult ajaxResult = null;
        try {
            try {
                filterSelectFeatureByExcelData(xlsxFile, selectFeature);
            } catch (Exception e) {
                log.error("读取Excel或处理列异常", e);
                return AjaxResult.error("Excel文件处理失败");
            }

            ajaxResult = fileClient.upperNamic(pythonBelowNamicDTO);
            // 处理返回结果，去除 NaN
            cleanNaNValues(ajaxResult);

            return ajaxResult;
        } catch (Exception e) {
            log.error("/upper/namic/second算法报错:{}", e.getMessage());
            return AjaxResult.error("算法未预测出结果,请重选新数据重试！", e);
        }


    }


    /**
     * 全三角Second
     */
    @PostMapping("/feign/upper/below/second")
    public AjaxResult upperBelowSecond(@RequestBody PythonUpperBelowDTO pythonUpperBelowDTO) {
        String xlsxFile = pythonUpperBelowDTO.getXlsxFile();
        List<String> selectFeature = pythonUpperBelowDTO.getSelectFeature();
        replaceStoneAndSandFeatures(selectFeature);

        // 递归检查 pythonBelowNamicDTO 中是否包含 NaN
        if (containsNaN(pythonUpperBelowDTO)) {
            return AjaxResult.error("数据错误，包含 NaN");
        }

        // 调用接口
        AjaxResult ajaxResult = null;
        try {
            try {
                filterSelectFeatureByExcelData(xlsxFile, selectFeature);
            } catch (Exception e) {
                log.error("读取Excel或处理列异常", e);
                return AjaxResult.error("Excel文件处理失败");
            }

            ajaxResult = fileClient.upperBelow(pythonUpperBelowDTO);
            // 处理返回结果，去除 NaN
            cleanNaNValues(ajaxResult);

            return ajaxResult;
        } catch (Exception e) {
            log.error("/upper/below/second算法报错:{}", e.getMessage());
            return AjaxResult.error("算法未预测出结果,请重选新数据重试！", e);
        }


    }


    private void replaceStoneAndSandFeatures(List<String> selectFeature) {
        replaceFeature(selectFeature, "石掺量", Arrays.asList("石5-10mm掺量", "石5-25mm掺量", "石20-40mm掺量", "石10-20mm掺量", "石10-30mm掺量", "石0-10mm掺量", "石20-31.5mm掺量"));
        replaceFeature(selectFeature, "石堆积密度", Arrays.asList("石5-10mm堆积密度(kg/m³)", "石5-25mm堆积密度(kg/m³)", "石20-40mm堆积密度(kg/m³)", "石10-20mm堆积密度(kg/m³)", "石10-30mm堆积密度(kg/m³)", "石0-10mm堆积密度(kg/m³)", "石20-31.5mm堆积密度(kg/m³)"));
        replaceFeature(selectFeature, "石紧密密度", Arrays.asList("石5-10mm紧密密度(kg/m³)", "石5-25mm紧密密度(kg/m³)", "石20-40mm紧密密度(kg/m³)", "石10-20mm紧密密度(kg/m³)", "石10-30mm紧密密度(kg/m³)", "石0-10mm紧密密度(kg/m³)", "石20-31.5mm紧密密度(kg/m³)"));
        replaceFeature(selectFeature, "石表观密度", Arrays.asList("石5-10mm表观密度(kg/m³)", "石5-25mm表观密度(kg/m³)", "石20-40mm表观密度(kg/m³)", "石10-20mm表观密度(kg/m³)", "石10-30mm表观密度(kg/m³)", "石0-10mm表观密度(kg/m³)", "石20-31.5mm表观密度(kg/m³)"));

        replaceFeature(selectFeature, "砂掺量", Arrays.asList("河砂粗3.1-3.7mm掺量", "河砂中2.3-3.0mm掺量", "河砂细1.6-2.2mm掺量", "机制砂中2.3-3.0mm掺量", "机制砂粗3.1-3.7mm掺量", "机制砂细1.6-2.2mm掺量", "机制砂0-4.75mm掺量", "机制砂0-9mm掺量"));
        replaceFeature(selectFeature, "砂细度", Arrays.asList("河砂粗3.1-3.7mm细度", "河砂中2.3-3.0mm细度", "河砂细1.6-2.2mm细度", "机制砂中2.3-3.0mm细度", "机制砂粗3.1-3.7mm细度", "机制砂细1.6-2.2mm细度", "机制砂0-4.75mm细度", "机制砂0-9mm细度"));
        replaceFeature(selectFeature, "砂堆积密度", Arrays.asList("河砂粗3.1-3.7mm堆积密度(kg/m³)", "河砂中2.3-3.0mm堆积密度(kg/m³)", "河砂细1.6-2.2mm堆积密度(kg/m³)", "机制砂中2.3-3.0mm堆积密度(kg/m³)", "机制砂粗3.1-3.7mm堆积密度(kg/m³)", "机制砂细1.6-2.2mm堆积密度(kg/m³)", "机制砂0-4.75mm堆积密度(kg/m³)", "机制砂0-9mm堆积密度(kg/m³)"));
        replaceFeature(selectFeature, "砂紧密密度", Arrays.asList("河砂粗3.1-3.7mm紧密密度(kg/m³)", "河砂中2.3-3.0mm紧密密度(kg/m³)", "河砂细1.6-2.2mm紧密密度(kg/m³)", "机制砂中2.3-3.0mm紧密密度(kg/m³)", "机制砂粗3.1-3.7mm紧密密度(kg/m³)", "机制砂细1.6-2.2mm紧密密度(kg/m³)", "机制砂0-4.75mm紧密密度(kg/m³)", "机制砂0-9mm紧密密度(kg/m³)"));
        replaceFeature(selectFeature, "砂表观密度", Arrays.asList("河砂粗3.1-3.7mm表观密度(kg/m³)", "河砂中2.3-3.0mm表观密度(kg/m³)", "河砂细1.6-2.2mm表观密度(kg/m³)", "机制砂中2.3-3.0mm表观密度(kg/m³)", "机制砂粗3.1-3.7mm表观密度(kg/m³)", "机制砂细1.6-2.2mm表观密度(kg/m³)", "机制砂0-4.75mm表观密度(kg/m³)", "机制砂0-9mm表观密度(kg/m³)"));
    }


    /**
     * 替换 selectFeature 中的指定特征
     */
    private void replaceFeature(List<String> selectFeature, String key, List<String> replacements) {
        if (selectFeature.contains(key)) {
            selectFeature.remove(key);
            selectFeature.addAll(replacements);
        }
    }

    /**
     * 递归检查对象是否包含 NaN
     */
    private boolean containsNaN(Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj instanceof Double && ((Double) obj).isNaN()) {
            return true;
        }
        if (obj instanceof Map) {
            return ((Map<?, ?>) obj).values().stream().anyMatch(this::containsNaN);
        }
        if (obj instanceof List) {
            return ((List<?>) obj).stream().anyMatch(this::containsNaN);
        }
        return false;
    }

    public void filterSelectFeatureByExcelData(String xlsxFilePath, List<String> selectFeature) throws Exception {
        try (FileInputStream fis = new FileInputStream(xlsxFilePath);
             Workbook workbook = new XSSFWorkbook(fis)) {

            Sheet sheet = workbook.getSheetAt(0); // 默认第一个sheet
            Row headerRow = sheet.getRow(0); // 表头行，假设是第0行
            if (headerRow == null) {
                return;
            }

            Iterator<String> iterator = selectFeature.iterator();

            while (iterator.hasNext()) {
                String feature = iterator.next();

                // 找到列索引
                int colIndex = -1;
                for (Cell cell : headerRow) {
                    if (cell.getCellType() == CellType.STRING && feature.equals(cell.getStringCellValue())) {
                        colIndex = cell.getColumnIndex();
                        break;
                    }
                }

                if (colIndex == -1) {
                    // selectFeature有，但Excel找不到对应列，直接删除这个feature
                    iterator.remove();
                    continue;
                }

                // 判断该列是否全是0
                boolean allZero = true;
                for (int r = 1; r <= sheet.getLastRowNum(); r++) {
                    Row row = sheet.getRow(r);
                    if (row == null) {
                        continue;
                    }
                    Cell cell = row.getCell(colIndex);
                    double val = 0;

                    if (cell == null) {
                        continue;
                    }

                    if (cell.getCellType() == CellType.NUMERIC) {
                        val = cell.getNumericCellValue();
                    } else if (cell.getCellType() == CellType.STRING) {
                        try {
                            val = Double.parseDouble(cell.getStringCellValue());
                        } catch (NumberFormatException e) {
                            allZero = false;
                            break;
                        }
                    } else {
                        // 如果非数值非字符串，视为非0处理，防止误删
                        allZero = false;
                        break;
                    }

                    if (val != 0) {
                        allZero = false;
                        break;
                    }
                }

                if (allZero) {
                    // 如果全是0，从selectFeature删掉该列
                    iterator.remove();
                }
            }
        }
    }

    /**
     * 递归清除 NaN 值
     */
    private void cleanNaNValues(Object obj) {
        if (obj instanceof Map) {
            ((Map<?, ?>) obj).replaceAll((k, v) -> {
                if (v instanceof Double && ((Double) v).isNaN()) {
                    return null; // 或者替换为 0.0
                }
                cleanNaNValues(v);
                return v;
            });
        } else if (obj instanceof List) {
            ((List<?>) obj).replaceAll(item -> {
                if (item instanceof Double && ((Double) item).isNaN()) {
                    return null; // 或者替换为 0.0
                }
                cleanNaNValues(item);
                return item;
            });
        }
    }
}
